﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Collections.ObjectModel;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;
using Microsoft.Phone.Controls.Maps.Platform;
using System.Windows.Media.Imaging;
using System.Windows.Markup;
using System.Windows.Controls.Primitives;
using CivilleWP7.Civille.Source;
using System.Data.Services.Client;
using CivilleWP7.CivilleDataServiceReference;
using CivilleWP7.Views.Pages;

namespace CivilleWP7
{
    public partial class LocalMapPage : PhoneApplicationPage
    {
        private GeoCoordinateWatcher watcher;
        private List<Task> currentTasks;
        private bool IsLightTheme;
        public LocalMapPage()
        {
            InitializeComponent();
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // using high accuracy
            watcher.MovementThreshold = 20; // use MovementThreshold to ignore noise in the signal
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
            watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
            watcher.Start();
            TaskPopUpGrid.Visibility = System.Windows.Visibility.Collapsed;
            currentTasks = new List<Task>();
            setBackground();
            this.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(LocalMapPage_OrientationChanged);
        }

        void LocalMapPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            if (e.Orientation == PageOrientation.Landscape || e.Orientation == PageOrientation.LandscapeLeft || e.Orientation == PageOrientation.LandscapeRight)
            {
                TaskGrid.RowDefinitions[0].Height = new GridLength(20, GridUnitType.Star);
                TaskGrid.RowDefinitions[1].Height = new GridLength(30, GridUnitType.Star);
                TaskGrid.RowDefinitions[2].Height = new GridLength(20, GridUnitType.Star);
                TaskGrid.RowDefinitions[3].Height = new GridLength(30, GridUnitType.Star);
            }
            else
            {
                TaskGrid.RowDefinitions[0].Height = new GridLength(15, GridUnitType.Star);
                TaskGrid.RowDefinitions[1].Height = new GridLength(55, GridUnitType.Star);
                TaskGrid.RowDefinitions[2].Height = new GridLength(15, GridUnitType.Star);
                TaskGrid.RowDefinitions[3].Height = new GridLength(15, GridUnitType.Star);
            }
        }
        void checkThemeColor()
        {
            var visibility = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"];
            if (visibility == Visibility.Visible)
                IsLightTheme = true;
            else
                IsLightTheme = false;
        }
        void setBackground()
        {
            checkThemeColor();
            ImageBrush myBrush = new ImageBrush();
            if(IsLightTheme)
                myBrush.ImageSource=new BitmapImage(new Uri("/Resources/Images/Backgroundwhite.jpg",UriKind.Relative));
            else
                myBrush.ImageSource = new BitmapImage(new Uri("/Resources/Images/Background.jpg",UriKind.Relative));
            ContentPanel.Background=myBrush;
        }

        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The Location Service is disabled or unsupported.
                    // Check to see whether the user has disabled the Location Service.
                    if (watcher.Permission == GeoPositionPermission.Denied)
                    {
                        MessageBoxButton ok = new MessageBoxButton();
                        MessageBox.Show("GeoLocation is disabled. Please enable it to detect tasks near you.", "Civille Application", ok);
                    }
                    else
                    {
                        MessageBoxButton ok = new MessageBoxButton();
                        MessageBox.Show("GeoLocation is not functioning on this device. You will not be able to detect tasks near you.", "Civille Application", ok);           
                    }
                    break;

                case GeoPositionStatus.Initializing:
                    // The Location Service is initializing.
                    break;

                case GeoPositionStatus.NoData:
                    // The Location Service is working, but it cannot get location data.
                    // Alert the user and enable the Stop Location button.
                    MessageBoxButton okay = new MessageBoxButton();
                    MessageBox.Show("GeoLocation cannot retrieve location information.", "Civille Application", okay);
                    break;

                case GeoPositionStatus.Ready:
                    // The Location Service is working and is receiving location data.
                    break;
            }
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            watcher.PositionChanged -= new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
            GetTasksForLocation(e.Position.Location.Latitude, e.Position.Location.Longitude);
            LocalMap.Center = new GeoCoordinate(e.Position.Location.Latitude, e.Position.Location.Longitude);
            LocalMap.ZoomLevel = 10;
            LocalMap.MapPan += new EventHandler<MapDragEventArgs>(LocalMap_MapPan);
        }

        private void GetTasksForLocation(double lat, double lang)
        {
            CivilleDataServiceConnector.AllTasksQuery.BeginExecute(OnTasksQueryComplete, CivilleDataServiceConnector.AllTasksQuery);
        }

        private void OnTasksQueryComplete(IAsyncResult result)
        {
            Dispatcher.BeginInvoke(() =>
            {
                DataServiceQuery<Task> query = result.AsyncState as DataServiceQuery<Task>;
                foreach (Task task in query.EndExecute(result))
                {
                    if (!TaskExists(task, currentTasks))
                    {
                        //Add the new task to the old ones.
                        currentTasks.Add(task);
                        Pushpin pin = new Pushpin();
                        Location pinLocation = new GeoCoordinate((double)task.Latitude, (double)task.Longitude);
                        pin.Location = pinLocation;
                        pin.Content = task.Title;
                        pin.Tag = task.ID;
                        pin.Background = App.Current.Resources["PhoneAccentBrush"] as Brush;
                        pin.Foreground = new SolidColorBrush(Colors.White);
                        //pin.Template = (ControlTemplate)(Application.Current.Resources["PushpinControlTemplate1"]);
                        pin.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(pin_Tap);
                        PushPinLayer.AddChild(pin, pinLocation);
                    }
                }
            });
        }

        bool TaskExists(Task task, List<Task> list)
        {
            foreach (Task currenTask in list)
            {
                if (currenTask.ID == task.ID)
                {
                    //If we already have the task just return here.
                    return true;
                }
            }
            return false;
        }

        private Task currentTask;

        void pin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            Task task = currentTasks.Where(x => x.ID == (Int32)(sender as Pushpin).Tag).First();
            currentTask = task;
            TaskPopUpGrid.Visibility = System.Windows.Visibility.Visible;
            TaskNameTextBlock.Text = task.Title;
            TaskDescriptionTextBlock.Text = task.Description;
            TaskPointsTextBlock.Text = task.Points.ToString();
            LocalMap.IsHitTestVisible = false; // Prevent mouse action on the page behind the Popup
            GoToTaskButton.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(GoToTaskButton_Tap);
            VerifyTaskButton.Tap += new EventHandler<System.Windows.Input.GestureEventArgs>(VerifyTaskButton_Tap);
        }

        void GoToTaskButton_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            TaskDetail.Task = currentTask;
            NavigationService.Navigate(new Uri(string.Format("/Views/Pages/TaskDetail.xaml"), UriKind.Relative));
        }

        void VerifyTaskButton_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Views/Pages/VerifyTask.xaml?id=" + currentTask.ID, UriKind.Relative));
        }

        void LocalMap_MapPan(object sender, MapDragEventArgs e)
        {
            //When map is panned we get the new center and redo the call for tasks.
            //Maybe we should make this call only if map center has shifted more than X.
            //Also maybe if the pan has stopped for 1 or 2 seconds (users usually pan repeatedly)
            GetTasksForLocation(LocalMap.Center.Latitude, LocalMap.Center.Longitude);
        }

        private void buttonRoad_Click(object sender, RoutedEventArgs e)
        {
            LocalMap.Mode = new RoadMode();
        }

        private void buttonAerial_Click(object sender, RoutedEventArgs e)
        {
            LocalMap.Mode = new AerialMode();
        }

        private void buttonZoomIn_Click(object sender, RoutedEventArgs e)
        {
            double zoom;
            zoom = LocalMap.ZoomLevel;
            LocalMap.ZoomLevel = ++zoom;
        }

        private void buttonZoomOut_Click(object sender, RoutedEventArgs e)
        {
            double zoom;
            zoom = LocalMap.ZoomLevel;
            LocalMap.ZoomLevel = --zoom;
        }

        private void TaskCloseButton_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            TaskPopUpGrid.Visibility = System.Windows.Visibility.Collapsed;
            LocalMap.IsHitTestVisible = true;
        }
    }
}
